package com.ruibang.glass.quality.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.common.domain.file.FileBusiness;
import com.ruibang.glass.quality.constant.QualityErrorCode;
import com.ruibang.glass.quality.domain.resp.DiagramData;
import com.ruibang.glass.quality.domain.req.QualityThicknessReq;
import com.ruibang.glass.quality.domain.resp.ThicknessExcelDataResp;
import com.ruibang.glass.quality.entity.QualityThickness;
import com.ruibang.glass.quality.entity.SpecsConfig;
import com.ruibang.glass.quality.feign.FileApi;
import com.ruibang.glass.quality.mapper.QualityThicknessMapper;
import com.ruibang.glass.quality.service.QualityThicknessService;
import com.ruibang.glass.quality.service.SpecsConfigService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.constant.CommonConstant;
import com.teaming.cloud.framework2.common.exception.ServiceException;
import com.teaming.cloud.framework2.common.model.ResultBody;
import com.teaming.cloud.framework2.common.pojo.PageRequest;
import com.teaming.cloud.framework2.common.pojo.PageResult;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 质量半成品厚度信息 服务实现类
 * </p>
 *
 * @author wujie
 * @since 2024-03-11
 */
@Service
public class QualityThicknessServiceImpl extends ServiceImpl<QualityThicknessMapper, QualityThickness> implements QualityThicknessService {

    @Autowired
    private FileApi fileApi;

//    @Autowired
//    private RedisSingleService redisService;

    @Autowired
    private RedisSingleService redisService;

    @Autowired
    private SpecsConfigService specsConfigService;

    private static final String ON_FLOW_SINGLE_THICKNESS = "非流向单线厚度数据";
    private static final String FLOW_SINGLE_THICKNESS = "流向单线厚度数据";
    private static final String FULL_THICKNESS = "整板厚度报告";
    private static final String NO_FLOW_FILE_ATTRIBUTE = "noFlow";

    private static final Integer INT_ELEVEN = 11;
    private static final Integer INT_TWELVE = 12;
    private static final Integer INT_THIRTEEN = 13;
    private static final Integer INT_FOURTEEN = 14;
    private static final Integer INT_FIFTEEN = 15;
    private static final Integer INT_SIXTEEN = 16;

    @Override
    public void saveInfo(QualityThickness qualityThickness) {
        LocalDateTime now = LocalDateTime.now();
        if(qualityThickness.getTransectTime()==null){
            qualityThickness.setTransectTime(now);
        }
        if(qualityThickness.getRecordTime()==null){
            qualityThickness.setRecordTime(now);
        }
        this.save(qualityThickness);
        //更新文件对应业务Id
        if(CollectionUtils.isNotEmpty(qualityThickness.getFileIds())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(qualityThickness.getFileIds());
            fileBusiness.setBusinessId(qualityThickness.getThicknessId());
            fileApi.updateBusinessById(fileBusiness);
        }

        if(qualityThickness.getFileBusiness()!=null){
            FileBusiness fileBusiness =  qualityThickness.getFileBusiness();
            fileBusiness.setBusinessId(qualityThickness.getThicknessId());
            fileApi.updateBusinessById(fileBusiness);
        }

    }

    @Override
    public void updateInfo(QualityThickness qualityThickness) {
        //更新文件信息
        if(CollectionUtils.isNotEmpty(qualityThickness.getDeleteFileIds())){
            fileApi.deleteByFileIds(qualityThickness.getDeleteFileIds());
        }
        //新增文件
        if(CollectionUtils.isNotEmpty(qualityThickness.getFileIds())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setBusinessId(qualityThickness.getThicknessId());
            fileBusiness.setFileIds(qualityThickness.getFileIds());
            fileApi.updateBusinessById(fileBusiness);
        }

        this.updateById(qualityThickness);
    }
    @Override
    public void delete(String id) {
        lambdaUpdate().eq(QualityThickness::getThicknessId, id).set(QualityThickness::getIsDelete, CommonConstant.ONE_STR).update();
    }


    @Override
    public PageResult<QualityThickness> queryPage(PageRequest<QualityThicknessReq> pageRequest) {
        final QualityThicknessReq param = pageRequest.getParam();
        final LambdaQueryWrapper<QualityThickness> lambda = new QueryWrapper<QualityThickness>().lambda();
        this.buildCondition(lambda,param);
        lambda.orderBy(true,false, QualityThickness::getTransectTime);
        final IPage<QualityThickness> page = this.page(new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize()), lambda);
        if(page!=null&& CollectionUtils.isNotEmpty(page.getRecords())){
            List<String> ids = page.getRecords().stream().map(c->c.getThicknessId()).collect(Collectors.toList());
            Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);
            List<SpecsConfig> configs = specsConfigService.getSpecsConfigByIds(page.getRecords().stream().map(qt->qt.getCheckRule()).collect(Collectors.toList()));
            Map<String, SpecsConfig> configMap = null;
            if(CollectionUtils.isNotEmpty(configs)){
                configMap = configs.stream().collect(Collectors.toMap(c->c.getSpecsId(),c->c,(c1,c2)->c1));
            }
            Map<String,List<String>> fileMap = null;
            ResultBody<List<FileBusiness>> resultBody = fileApi.getFileBusinessByIds(ids);
            if(resultBody!=null&& CollectionUtils.isNotEmpty(resultBody.getData())){
                fileMap = resultBody.getData().stream().collect(Collectors.toMap(f->f.getBusinessId(), f->f.getFileIds(),(f1, f2)->f1));
            }
            for (QualityThickness qt : page.getRecords()) {
                if(fileMap!=null){
                    qt.setFileIds(fileMap.get(qt.getThicknessId()));
                }
                if(userMap!=null){
                    qt.setUserName(userMap.get(qt.getUserId())==null?"":userMap.get(qt.getUserId()).toString());
                }
                if(configMap!=null){
                    qt.setSpecsConfig(configMap.get(qt.getCheckRule()));
                }
            }
        }

        PageResult<QualityThickness> pr = new PageResult(page);
        return pr;
    }

    @Override
    public List<QualityThickness> queryQualityThickness(QualityThicknessReq thicknessReq) {
        final LambdaQueryWrapper<QualityThickness> lambda = new QueryWrapper<QualityThickness>().lambda();
        this.buildCondition(lambda,thicknessReq);
        lambda.orderBy(true,true, QualityThickness::getTransectTime);
        List<QualityThickness> list = this.list(lambda);
        if(CollectionUtils.isNotEmpty(list)){
            Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);
            for (QualityThickness qt : list) {
                if(userMap!=null){
                    qt.setUserName(userMap.get(qt.getUserId())==null?"":userMap.get(qt.getUserId()).toString());
                }
            }

        }
        return list;
    }

    @Override
    public ThicknessExcelDataResp importThickness(List<MultipartFile> files) {
        ThicknessExcelDataResp thickness = new ThicknessExcelDataResp();
        if(CollectionUtils.isNotEmpty(files)){
            List<String> fileIds = new ArrayList<>();
            for (MultipartFile file : files) {
                InputStream inputStream = null;
                try {
                    inputStream = file.getInputStream();
                    Workbook workbook = WorkbookFactory.create(inputStream);
                    int sheetCount = workbook.getNumberOfSheets();
                    if(sheetCount == CommonConstant.ONE_INT){
                        Sheet sheet = workbook.getSheetAt(CommonConstant.ZERO_INT);
                        if(sheet!=null){
                            Row row0 = sheet.getRow(CommonConstant.ZERO_INT);
                            Cell cell0 = row0.getCell(CommonConstant.ZERO_INT);
                            String name = cell0.getStringCellValue();
                            if(!StringUtils.isEmpty(name)){
                                if(name.contains(ON_FLOW_SINGLE_THICKNESS)){
                                    Row row8 = sheet.getRow(CommonConstant.SEVEN_INT);
                                    Cell cell8 = row8.getCell(CommonConstant.ONE_INT); //非流向厚度极大
                                    thickness.setNoFlowThicknessMax((float)cell8.getNumericCellValue());
                                    Row row9 = sheet.getRow(CommonConstant.EIGHT_INT);
                                    Cell cell9 = row9.getCell(CommonConstant.ONE_INT); //非流向厚度极小
                                    thickness.setNoFlowThicknessMin((float)cell9.getNumericCellValue());
                                    Row row10 = sheet.getRow(CommonConstant.NINE_INT);
                                    Cell cell10 = row10.getCell(CommonConstant.ONE_INT); //非流向厚度平均
                                    thickness.setNoFlowThicknessAverage((float)cell10.getNumericCellValue());
                                    Row row11 = sheet.getRow(CommonConstant.TEN_INT);
                                    Cell cell11 = row11.getCell(CommonConstant.ONE_INT); //非流向厚度极差
                                    thickness.setChangeNoFlow((float)cell11.getNumericCellValue());
                                    Row row13 = sheet.getRow(INT_TWELVE);
                                    Cell cell13 = row13.getCell(CommonConstant.ONE_INT); //非流向每20mm极差
                                    thickness.setChangeNoFlowTwenty((float)cell13.getNumericCellValue());
                                    Row row14 = sheet.getRow(INT_THIRTEEN);
                                    Cell cell14 = row14.getCell(CommonConstant.ONE_INT); //非流向每100mm极差
                                    thickness.setChangeNoFlowOneHundred((float)cell14.getNumericCellValue());
                                    Row row15 = sheet.getRow(INT_FOURTEEN);
                                    Cell cell15 = row15.getCell(CommonConstant.ONE_INT); //非流向每300mm极差
                                    thickness.setChangeNoFlowThreeHundred((float)cell15.getNumericCellValue());
                                    Row row16 = sheet.getRow(INT_FIFTEEN);
                                    Cell cell16 = row16.getCell(CommonConstant.ONE_INT); //近端平均
                                    thickness.setNearAverage((float)cell16.getNumericCellValue());
                                    Row row17 = sheet.getRow(INT_SIXTEEN);
                                    Cell cell17 = row17.getCell(CommonConstant.ONE_INT); //远端平均
                                    thickness.setFarAverage((float)cell17.getNumericCellValue());


                                    ResultBody<String> resultBody = fileApi.uploadFile(file);
                                    if(resultBody!=null&& StringUtils.isNotBlank(resultBody.getData())){
                                        FileBusiness fileBusiness = new FileBusiness();
                                        fileBusiness.setFileIds(Arrays.asList(resultBody.getData()));
                                        thickness.setFileBusiness(fileBusiness);

                                        //取后续的数据放入redis用于折线图快速加载
                                        int rowNum = sheet.getLastRowNum();
                                        if(rowNum>16){
                                            List<DiagramData> diagramDatas = new ArrayList<>();
                                            for(int i=17;i<=rowNum;i++){
                                                DiagramData diagramData = new DiagramData();
                                                Row row = sheet.getRow(i);
                                                Cell cellx = row.getCell(CommonConstant.ZERO_INT);
                                                diagramData.setX(cellx.getStringCellValue());
                                                Cell celly = row.getCell(CommonConstant.ONE_INT);
                                                diagramData.setY(String.valueOf(celly.getNumericCellValue()));
                                                diagramDatas.add(diagramData);
                                            }
                                            if(CollectionUtils.isNotEmpty(diagramDatas)){
                                                redisService.set(NO_FLOW_FILE_ATTRIBUTE.concat(CommonConstant.SpecialSign.UNDERLINE.getName().concat(resultBody.getData())), JSON.toJSONString(diagramDatas));
                                            }
                                        }
                                    }


                                }else if(name.contains(FLOW_SINGLE_THICKNESS)){
                                    Row row8 = sheet.getRow(CommonConstant.SEVEN_INT);
                                    Cell cell8 = row8.getCell(CommonConstant.ONE_INT); //流向厚度极大
                                    thickness.setFlowThicknessMax((float)cell8.getNumericCellValue());
                                    Row row9 = sheet.getRow(CommonConstant.EIGHT_INT);
                                    Cell cell9 = row9.getCell(CommonConstant.ONE_INT); //流向厚度极小
                                    thickness.setFlowThicknessMin((float)cell9.getNumericCellValue());
                                    Row row10 = sheet.getRow(CommonConstant.NINE_INT);
                                    Cell cell10 = row10.getCell(CommonConstant.ONE_INT); //流向厚度平均
                                    thickness.setFlowThicknessAverage((float)cell10.getNumericCellValue());
                                    Row row11 = sheet.getRow(CommonConstant.TEN_INT);
                                    Cell cell11 = row11.getCell(CommonConstant.ONE_INT); //流向厚度极差
                                    thickness.setChangeFlow((float)cell11.getNumericCellValue());

                                    ResultBody<String> resultBody = fileApi.uploadFile(file);
                                    if(resultBody!=null&& StringUtils.isNotBlank(resultBody.getData())){
                                        fileIds.add(resultBody.getData());
                                    }
                                }
                            }

                        }
                    }else if(sheetCount == CommonConstant.TWO_INT){
                        Sheet sheet = workbook.getSheetAt(CommonConstant.ONE_INT);
                        if(sheet!=null){
                            Row row0 = sheet.getRow(CommonConstant.ZERO_INT);
                            Cell cell = row0.getCell(CommonConstant.ZERO_INT);
                            String name = cell.getStringCellValue();
                            if(name.contains(FULL_THICKNESS)){
                                Row row4 = sheet.getRow(CommonConstant.THREE_INT);
                                Cell cell4 = row4.getCell(INT_ELEVEN); //流向厚度极大
                                thickness.setFullThicknessMax((float)cell4.getNumericCellValue());
                                Row row5 = sheet.getRow(CommonConstant.FOUR_INT);
                                Cell cell5 = row5.getCell(INT_ELEVEN); //流向厚度极小
                                thickness.setFullThicknessMin((float)cell5.getNumericCellValue());
                                Row row6 = sheet.getRow(CommonConstant.FIVE_INT);
                                Cell cell6 = row6.getCell(INT_ELEVEN); //流向厚度平均
                                thickness.setFullThicknessAverage((float)cell6.getNumericCellValue());
                                Row row7 = sheet.getRow(CommonConstant.SIX_INT);
                                Cell cell7 = row7.getCell(INT_ELEVEN); //流向厚度极差
                                thickness.setChangeFull((float)cell7.getNumericCellValue());
                                ResultBody<String> resultBody = fileApi.uploadFile(file);
                                if(resultBody!=null&& StringUtils.isNotBlank(resultBody.getData())){
                                    fileIds.add(resultBody.getData());
                                }
                            }
                        }
                    }

                } catch (IOException e) {
                    log.error("执行流操作异常:"+e.getMessage());
                    throw new ServiceException(QualityErrorCode.SEMI_IMPORT_FILE_ERROR.getCode(),QualityErrorCode.SEMI_IMPORT_FILE_ERROR.getMsg());
                }
            }
            thickness.setFileIds(fileIds);
        }
        return thickness;
    }

    @Override
    public List<DiagramData> lineGraph(String thicknessId) {
        List<DiagramData> diagramDatas = new ArrayList<>();
        if(StringUtils.isNotBlank(thicknessId)){
            Serializable serializable = redisService.get(NO_FLOW_FILE_ATTRIBUTE.concat(CommonConstant.SpecialSign.UNDERLINE.getName().concat(thicknessId)));
            if(serializable!=null && StringUtils.isNotBlank(serializable.toString())){
                diagramDatas = JSON.parseArray(serializable.toString(),DiagramData.class);
                return diagramDatas;
            }
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setBusinessId(thicknessId);
            ResultBody<List<String>> resultBody = fileApi.getPreviewByBusinessParam(fileBusiness);
            if(resultBody!=null&&CollectionUtils.isNotEmpty(resultBody.getData())){
                String address = resultBody.getData().get(0);
                if(StringUtils.isNotEmpty(address)){
                    InputStream is = null;
                    Workbook workbook = null;
                    try {
                        URL url = new URL(address);
                        URLConnection connection = url.openConnection();
                        is = connection.getInputStream();
                        workbook = WorkbookFactory.create(is);
                        int sheetCount = workbook.getNumberOfSheets();
                        if(sheetCount == CommonConstant.ONE_INT){
                            Sheet sheet = workbook.getSheetAt(CommonConstant.ZERO_INT);
                            int rowNum = sheet.getLastRowNum();
                            if(rowNum>16){
                                for(int i=17;i<=rowNum;i++){
                                    DiagramData diagramData = new DiagramData();
                                    Row row = sheet.getRow(i);
                                    Cell cellx = row.getCell(CommonConstant.ZERO_INT);
                                    diagramData.setX(cellx.getStringCellValue());
                                    Cell celly = row.getCell(CommonConstant.ONE_INT);
                                    diagramData.setY(String.valueOf(celly.getNumericCellValue()));
                                    diagramDatas.add(diagramData);
                                }
                                if(CollectionUtils.isNotEmpty(diagramDatas)){
                                    redisService.set( NO_FLOW_FILE_ATTRIBUTE.concat(CommonConstant.SpecialSign.UNDERLINE.getName().concat(thicknessId)), JSON.toJSONString(diagramDatas));
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("读取文件流异常:"+e.getMessage());
                    }finally {
                        try {
                            if(is!=null){
                                is.close();
                            }
                            if(workbook!=null){
                                workbook.close();
                            }

                        } catch (IOException e) {
                            log.error("流关闭异常:"+e.getMessage());
                        }
                    }

                }
            }
        }

        return diagramDatas;
    }

    /**
     * 构造查询条件
     * @param lambda
     * @param param
     */
    private void buildCondition(LambdaQueryWrapper<QualityThickness> lambda, QualityThicknessReq param){
        lambda.eq(QualityThickness::getIsDelete, CommonConstant.ZERO_STR);
        if(null == param) return;
        if(StringUtils.isNotBlank(param.getThicknessId())){
            lambda.eq(QualityThickness::getThicknessId, param.getThicknessId());
        }
        if(StringUtils.isNotBlank(param.getProductLine())){
            lambda.eq(QualityThickness::getProductLine, param.getProductLine());
        }
        if(StringUtils.isNotBlank(param.getGlassId())){
            lambda.eq(QualityThickness::getGlassId, param.getGlassId());
        }
        if(StringUtils.isNotBlank(param.getGlassType())){
            lambda.eq(QualityThickness::getGlassType, param.getGlassType());
        }
        if(StringUtils.isNotBlank(param.getGlassModel())){
            lambda.eq(QualityThickness::getGlassModel, param.getGlassModel());
        }
        if(StringUtils.isNotBlank(param.getCheckRule())){
            lambda.eq(QualityThickness::getCheckRule, param.getCheckRule());
        }
        if(StringUtils.isNotBlank(param.getDecide())){
            lambda.eq(QualityThickness::getDecide, param.getDecide());
        }
        if(StringUtils.isNotBlank(param.getUserId())){
            lambda.eq(QualityThickness::getUserId, param.getUserId());
        }

        if(param.getRecordStartTime()!=null&&param.getRecordEndTime()!=null){
            lambda.ge(QualityThickness::getRecordTime, param.getRecordStartTime());
            lambda.le(QualityThickness::getRecordTime, param.getRecordEndTime());
        }
        if(param.getTransectStartTime()!=null&&param.getTransectEndTime()!=null){
            lambda.ge(QualityThickness::getTransectTime, param.getTransectStartTime());
            lambda.le(QualityThickness::getTransectTime, param.getTransectEndTime());
        }


        if(StringUtils.isNotBlank(param.getTeam())){
            lambda.eq(QualityThickness::getTeam, param.getTeam());
        }
        if(StringUtils.isNotBlank(param.getIsRetrospect())){
            lambda.eq(QualityThickness::getIsRetrospect, param.getIsRetrospect());
        }


    }
}
